﻿using Core.Utility.Helper;
using FastServer.SwaggerDocument;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace FastServer
{

    /// <summary>
    /// Swagger文档配置选项
    /// </summary>
    public sealed class SwaggerDocumentSettingsOptions : IConfigurableOptions<SwaggerDocumentSettingsOptions>
    {
        /// <summary>
        /// 文档标题
        /// </summary>
        public string? DocumentTitle { get; set; }

        /// <summary>
        /// 默认分组名
        /// </summary>
        public string? DefaultGroupName { get; set; }

        /// <summary>
        /// 启用授权支持
        /// </summary>
        public bool? EnableAuthorized { get; set; }

        /// <summary>
        /// 配置规范化文档地址
        /// </summary>
        public string? RoutePrefix { get; set; }

        /// <summary>
        /// 文档展开设置
        /// </summary>
        public DocExpansion DocExpansionState { get; set; } = DocExpansion.List;

        /// <summary>
        /// XML 描述文件
        /// </summary>
        public List<string> XmlComments { get; set; } = new List<string>();

        /// <summary>
        /// 分组信息
        /// </summary>
        public List<SwaggerOpenApiInfo>? GroupOpenApiInfos { get; set; }

        /// <summary>
        /// 安全定义
        /// </summary>
        public List<SwaggerOpenApiSecurityScheme>? SecurityDefinitions { get; set; }

        /// <summary>
        /// 配置 Servers
        /// </summary>
        public List<OpenApiServer>? Servers { get; set; }

        /// <summary>
        /// 隐藏 Servers
        /// </summary>
        public bool? HideServers { get; set; }

        /// <summary>
        /// 默认 swagger.json 路由模板
        /// </summary>
        public string? RouteTemplate { get; set; }

        /// <summary>
        /// 配置安装第三方包的分组名
        /// </summary>
        public List<string> PackagesGroups { get; set; } = new List<string>();

        /// <summary>
        /// 启用枚举 Schema 筛选器
        /// </summary>
        public bool? EnableEnumSchemaFilter { get; set; }

        /// <summary>
        /// 启用标签排序筛选器
        /// </summary>
        public bool? EnableTagsOrderDocumentFilter { get; set; }

        /// <summary>
        /// 服务目录（修正 IIS 创建 Application 问题）
        /// </summary>
        public string? ServerDir { get; set; }

        /// <summary>
        /// 配置规范化文档登录信息
        /// </summary>
        public SwaggerOpenApiLoginInfo LoginInfo { get; set; } = new SwaggerOpenApiLoginInfo();

        /// <summary>
        /// 启用 All Groups 功能
        /// </summary>
        public bool? EnableAllGroups { get; set; }

        /// <summary>
        /// 枚举类型生成值类型
        /// </summary>
        public bool? EnumToNumber { get; set; }

        /// <summary>
        /// 后期配置
        /// </summary>
        /// <param name="options"></param>
        /// <param name="configuration"></param>
        public void PostConfigure(SwaggerDocumentSettingsOptions options, IConfiguration configuration)
        {
            options.DocumentTitle ??= "Swagger Api Document";
            options.DefaultGroupName ??= "Default";
            //options.RoutePrefix ??= "api";    // 可以通过 UseInject() 配置，所以注释
            //options.DocExpansionState ??= DocExpansion.List;

            // 加载项目注册和模块化/插件注释
            var frameworkPackageName = ReflectHelper.GetAssemblyName(GetType());
            var projectXmlComments = App.Assemblies.Where(u => u.GetName().Name != frameworkPackageName).Select(t => t.GetName().Name);
            var externalXmlComments = App.ExternalAssemblies.Any() ? App.Settings?.ExternalAssemblies.Select(u => u.EndsWith(".dll") ? u[0..^4] : u) : Array.Empty<string>();            

            GroupOpenApiInfos ??= new List<SwaggerOpenApiInfo>
            {
                new SwaggerOpenApiInfo()
                {
                    Group = options.DefaultGroupName
                }
            };

            EnableAuthorized ??= true;
            if (EnableAuthorized == true)
            {
                SecurityDefinitions ??= new List<SwaggerOpenApiSecurityScheme>
                {
                    new SwaggerOpenApiSecurityScheme
                    {
                        Id="Bearer",
                        Type= SecuritySchemeType.Http,
                        Name="Authorization",
                        Description="JWT Authorization header using the Bearer scheme.",
                        BearerFormat="JWT",
                        Scheme="bearer",
                        In= ParameterLocation.Header,
                        Requirement=new SwaggerOpenApiSecurityRequirementItem
                        {
                            Scheme=new OpenApiSecurityScheme
                            {
                                Reference=new OpenApiReference
                                {
                                    Id="Bearer",
                                    Type= ReferenceType.SecurityScheme
                                }
                            },
                            Accesses = new List<string>()
                        }
                    }
                };
            }

            Servers ??= new List<OpenApiServer>();
            HideServers ??= true;
            RouteTemplate ??= "swagger/{documentName}/swagger.json";
            EnableEnumSchemaFilter ??= true;
            EnableTagsOrderDocumentFilter ??= true;
            EnableAllGroups ??= false;
            EnumToNumber ??= false;
        }
    }
}
